﻿' Author: Ben Glasser WP3
' Date: 11-15-11
' File: Map.vb
' Purpose: parses a saved map file inorder to load a valid map for the game

Imports System.IO
Imports Frupal.Cell

<Serializable()> Public Class Map
    ' define Map Vars
    Dim trimArr() As Char = {" "}
    Dim map(,) As Cell
    Dim mapID As String
    Dim mapFile As String
    Dim dimension As Integer
    Dim heroLocation As Point
    Dim energy As Integer
    Dim whiffles As Integer
    Dim newCell As Cell
    Dim lineCount As Integer
    Dim separator As New String("#########################")

    ' enumaerate Cell values for readability
    Private Enum CELLNFO_
        X = 1
        Y = 0
        VISIBILITY = 2
        TERRAIN = 3
        CONTENT = 4
    End Enum

    ' Default Constructor
    Sub New()
        InitVars()
        map = New Cell(dimension, dimension) {}
        mapInit()
    End Sub

    ' Map class constructor
    Sub New(ByVal mapFile As String)
        lineCount = 0
        Dim lineBuff As New String("")
        Me.mapFile = mapFile
        InitVars()
        Dim inFile As StreamReader
        inFile = My.Computer.FileSystem.OpenTextFileReader(mapFile)
        ' set mapID and dimension
        lineBuff = Read(inFile)
        If lineBuff.Equals(separator) Then
            Corrupt()
            mapInit()
            Exit Sub
        Else
            Try
                mapID = lineBuff
            Catch
                Corrupt()
                mapInit()
                Exit Sub
            End Try
        End If
        lineBuff = Read(inFile)
        If lineBuff.Equals(separator) Then
            Corrupt()
            mapInit()
            Exit Sub
        Else
            Try
                dimension = lineBuff
            Catch
                Corrupt()
                mapInit()
                Exit Sub
            End Try
        End If
        map = New Cell(dimension, dimension) {}
        mapInit()
        Try
            ParseGameState(inFile)
        Catch
            Corrupt()
            mapInit()
            Exit Sub
        End Try
    End Sub

    '****************************[ Private Methods ]******************************************
    ' this function trims whitespace and skips blank lines
    Private Function Read(ByRef infile As StreamReader) As String
        Dim lineBuff As New String(infile.ReadLine().Trim(trimArr))
        lineCount += 1
        If lineBuff.Equals("") Then
            Read(infile)
        End If
        Return lineBuff
    End Function
    ' parse game state section of the text file
    Private Sub ParseGameState(ByRef infile As StreamReader)
        'HACK make sure you get this to work
        Dim lineBuff As New String("")
        Dim location(0 To 1) As String
        If (infile.ReadLine.Equals(separator)) Then
            lineCount += 1
            location = infile.ReadLine().Split(",")
            lineCount += 1
            If (location(0) <= dimension And location(0) >= 0 And _
                location(1) <= dimension And location(0) >= 0) Then
                heroLocation.X = location(0)
                heroLocation.Y = location(1)
            Else
                Corrupt()
                mapInit()
                Exit Sub
                End
            End If
        Else
            Corrupt()
            mapInit()
            Exit Sub
        End If

        energy = infile.ReadLine()
        lineCount += 1
        whiffles = infile.ReadLine()
        lineCount += 1
        'infile.ReadLine()
        lineBuff = New String(infile.ReadLine())
        lineCount += 1
        ' parse game state
        While (Not lineBuff.Equals("#########################"))
            GameWindow.Inventory.Items.Add(lineBuff)
            lineBuff = New String(infile.ReadLine())
            lineCount += 1
            If infile.EndOfStream Then
                Corrupt()
                mapInit()
                Exit Sub
            End If
        End While
        ' finish parsing the rest of the document
        ParseCells(infile)
    End Sub

    Private Sub ParseCells(ByRef infile As StreamReader)
        Dim line(0 To 4) As String
        ' parse cell information and insert into map
        While (Not infile.EndOfStream)
            line = infile.ReadLine.Split(",")
            lineCount += 1
            ' ensure cell location is within given range
            If (line(0) >= dimension Or line(1) >= dimension Or _
                line(0) < 0 Or line(1) < 0) Then
                Corrupt()
                mapInit()
            Else
                map(line(CELLNFO_.X), line(CELLNFO_.Y)).SetVisible(line(CELLNFO_.VISIBILITY))
                map(line(CELLNFO_.X), line(CELLNFO_.Y)).SetTerrain(line(CELLNFO_.TERRAIN))
                map(line(CELLNFO_.X), line(CELLNFO_.Y)).SetContent(line(CELLNFO_.CONTENT).ToLower.Trim(trimArr))
            End If
        End While
    End Sub
    Private Sub Corrupt()
        MsgBox("File Corrupt! Error at line: " + lineCount.ToString)
    End Sub
    ' variable initialization
    Private Sub InitVars()
        ' default game state
        map = New Cell(25, 25) {}
        mapID = "untitled"
        dimension = 25
        heroLocation = New Point(0, 0)
        energy = 100
        whiffles = 100
        newCell = New Cell
    End Sub

    ' initialize all cells in map to invisible cells of meadows with no content
    Private Sub mapInit()
        For i As Integer = 0 To dimension
            For j As Integer = 0 To dimension
                map(i, j) = New Cell(False, 0, "None")
            Next
        Next
    End Sub
    Private Function visibility(ByVal val As Boolean) As String
        If (val) Then
            Return "1"
        Else
            Return "0"
        End If
    End Function
    ' retruns a random number between 0 and myNum inclusive
    Private Function Get_Random(ByVal myNum As Integer) As Integer
        Return Math.Round(myNum * Rnd(System.DateTime.Now.Millisecond))
    End Function

    '****************************[ Public Methods ]******************************************
    Function getMap()
        Return map
    End Function

    Function getDimension() As Integer
        Return dimension
    End Function

    Function GetEnergy() As Integer
        Return energy
    End Function

    Function GetWhiffles() As Integer
        Return whiffles
    End Function

    Function GetHeroLocation() As Point
        Return heroLocation
    End Function

    Sub SetHeroLocation(ByVal loc As Point)
        heroLocation = loc
    End Sub

    Sub MoveHeroHorizontal(ByVal move As Integer)
        '+++++If trying to walk off map++++++
        If (heroLocation.X = 0 And move = -1) Or (heroLocation.X = dimension And move = 1) Then
            heroLocation.X += 0
            MsgBox("You cannot leave the map!")
        Else
            '+++++If trying to walk into water cell++++++
            If map(heroLocation.X + move, heroLocation.Y).GetTerrain = 2 Then
                heroLocation.X += 0
                MsgBox("You are trying to enter a river")
                ''+++++If trying to walk into a wall++++++
            ElseIf map(heroLocation.X + move, heroLocation.Y).GetTerrain = 3 Then
                heroLocation.Y += 0
                MsgBox("You are trying to walk through a wall")
            Else
                heroLocation.X += move
            End If
            If getCellContent(heroLocation) <> "none" Then
                HandleInventory(getCellContent(heroLocation))
            End If

        End If
    End Sub

    Sub MoveHeroVertical(ByVal move As Integer)
        '+++++If trying to walk off map++++++

        If (heroLocation.Y = 0 And move = -1) Or (heroLocation.Y = dimension And move = 1) Then
            heroLocation.X += 0
            MsgBox("You cannot leave the map!")
            '+++++If trying to walk into water cell++++++
        Else
            If map(heroLocation.X, heroLocation.Y + move).GetTerrain = 2 Then
                heroLocation.Y += 0
                MsgBox("You are trying to enter a river")
            ElseIf map(heroLocation.X, heroLocation.Y + move).GetTerrain = 3 Then
                heroLocation.Y += 0
                MsgBox("You are trying to walk through a wall")
            Else
                heroLocation.Y += move
            End If
        End If
        
    End Sub

    Function cellIsVisible(ByVal loc As Point) As Boolean
        Return map(loc.X, loc.Y).IsVisible
    End Function

    Function getCellContent(ByVal loc As Point) As String
        Return map(loc.X, loc.Y).GetContent
    End Function

    Function getCellTerrain(ByVal loc As Point) As Integer
        Return map(loc.X, loc.Y).GetTerrain
    End Function
    Function HandleInventory(ByVal content As String) As Integer
        Select Case getCellContent(heroLocation)
            Case "axe"
                MsgBox("You have encountered an Axe!, Would you like to purchase it?")

            Case "binoculars"

            Case "blackberry bushes"

            Case "boulder"

            Case "chainsaw"

            Case "chisel"

            Case "hatchet"

            Case "jackhammer"

            Case "machete"

            Case "powerbar"

            Case "royal diamonds"

            Case "sledge"

            Case "treasure chest"

            Case "boat"

        End Select
        Return 0
    End Function

    ' this function writes a string in the probper .map format of the current state of the map.
    Overrides Function ToString() As String
        Dim myString As String = ""
        myString = mapID + vbNewLine
        myString = myString + dimension.ToString + vbNewLine
        myString = myString + separator + vbNewLine
        myString = myString + heroLocation.X.ToString + "," + heroLocation.Y.ToString + vbNewLine
        myString = myString + energy.ToString + vbNewLine
        myString = myString + whiffles.ToString + vbNewLine
        For i As Integer = 0 To (GameWindow.Inventory.Items.Count - 1)
            myString = myString + GameWindow.Inventory.Items.Item(i) + vbNewLine
        Next
        myString = myString + separator
        For i As Integer = 0 To (dimension - 1)
            For j = 0 To (dimension - 1)
                myString = myString + vbNewLine _
                       + j.ToString _
                       + "," + i.ToString _
                       + "," + visibility(map(i, j).IsVisible()) _
                       + "," + map(i, j).GetTerrain().ToString _
                       + "," + map(i, j).GetContent()
            Next
        Next
        Return myString
    End Function

    ' this function creates a random map with a given name and dimension, density refers to an
    ' integer from 0 - 100 which determins how much random "content" is placed on the board
    ' 0 means no contenet, 100 means nearly every cell which is no a wall or water has content.
    Public Sub Random(ByVal name As String, ByVal dimension As Integer, ByVal density As Integer)
        Dim terr As Integer
        Dim cont As Integer

        mapID = name
        Me.dimension = dimension
        whiffles = 1000
        energy = 100

        ' create map
        For i As Integer = 0 To (dimension - 1)
            For j As Integer = 0 To (dimension - 1)
                terr = Get_Random(3)
                cont = Get_Random(17)
                ' if terrain is not water or a wall
                If terr < 2 And Get_Random(100) < density Then
                    map(i, j) = New Cell(True, terr, cont)
                Else ' else don't add content
                    map(i, j) = New Cell(True, terr, 0)
                End If
            Next
        Next

        ' format the cell in which to place the royal jewels
        Dim x As Integer = Get_Random(dimension - 1)
        Dim y As Integer = Get_Random(dimension - 1)
        map(x, y).SetContent("royal diamonds")
        map(x, y).SetTerrain(0)

        ' place hero in starting location
        map(0, 0).SetContent("none")
        map(0, 0).SetTerrain(0)
        heroLocation = (New Point(0, 0))
    End Sub

    Public Sub Save(ByVal mapfile As String)
        Try
            Dim myStream As New StreamWriter(mapfile)
            Dim myString As String = Me.ToString()
            myStream.WriteLine(myString)
            myStream.Close()
        Catch e As Exception
            MsgBox("File In Use! " + e.ToString)
        End Try
    End Sub



End Class
